package ru.papergames.model.proxies
{
	import mx.rpc.AsyncToken;
	import mx.rpc.IResponder;
	import mx.rpc.http.HTTPService;
	import mx.utils.ObjectUtil;
	import mx.utils.URLUtil;
	
	public class HTTPProxy extends BaseProxy
	{
		
		public static const SERVICE_ERROR:String = 'HTTPProxy.SERVICE_ERROR';		
		public static const SERVICE_SUCCESS:String = 'HTTPProxy.SERVICE_SUCCESS';
		
		public static const UNKNOWN_RESULT_HANDLER:String = 'HTTPProxy.UNKNOWN_RESULT_HANDLER';
		
		public static const START_NOTE_POSTFIX:String = '_HTTPProxy_START';
		public static const SUCCESS_NOTE_POSTFIX:String = '_HTTPProxy_RESULT';
		public static const FAULT_NOTE_POSTFIX:String = '_HTTPProxy_FAULT';
		public static const COMPLETE_NOTE_POSTFIX:String = '_HTTPProxy_COMPLETE';
		
		public static const START:String = 'HTTPProxy_START';
		public static const COMPLETE:String = 'HTTPProxy_COMPLETE';
		
		private var service:HTTPService;
		
		private var _serviceURL:String = '';
		private var _timeout:int = 0;
		
		public function HTTPProxy(pName:String, url:String, data:Object, timeout:int = 0)
		{
			super(pName, data);
			_serviceURL = url;
			_timeout = timeout ? timeout : _timeout;
		}
		
		override public function onRegister():void {
			super.onRegister();
			service = new HTTPService();
			service.resultFormat = 'e4x';
			service.url = URLUtil.getFullURL(this.settingsProxy.rootURL, _serviceURL);
			service.method = 'POST';
			service.requestTimeout = _timeout;
			
			logger.debug('URL = ' + service.url);
		}
		
		override public function onRemove():void {
			super.onRemove();
			service = null;
		}
		
		
		protected function get settingsProxy():SettingsProxy {
			return this.getProxy(SettingsProxy.NAME) as SettingsProxy;
		}		
		
		
		public function call(method:String, params:Object = null):void {
			
			var paramsDump:String = ObjectUtil.toString(params); 
			
			logger.debug('Invoking "' + method + '"; serviceURL=' + _serviceURL + ".\nParams: \n" + paramsDump);
			
			var token:AsyncToken = service.send(params);
			token.addResponder( getResponderForMethod(method) );
			
			facade.sendNotification(START, method); 
			facade.sendNotification(method + START_NOTE_POSTFIX);
		}
		
		protected function generic_Result(data:XML):String {
						
			facade.sendNotification(SERVICE_SUCCESS, data.toXMLString());
			
			var isSuccess:Boolean = String(data.data.success) == 'true';
			var method:String = String(data.@method);
			
			return isSuccess ? method.concat(SUCCESS_NOTE_POSTFIX) : method.concat(FAULT_NOTE_POSTFIX);
		}
		
		protected function generic_Fault(message:String):void {
			logger.error('generic_Fault: ' + message);
			facade.sendNotification(SERVICE_ERROR, message);
		}
		
		protected function getResponderForMethod(method:String):IResponder {
			//gets function for responding
			var resp:BaseResponder = new BaseResponder(	this.facade, 
														method.concat(SUCCESS_NOTE_POSTFIX), 
														method.concat(FAULT_NOTE_POSTFIX),
													   	COMPLETE);
			
 			var resultFunction:String = method + '_Result';
			var faultFunction:String = method + '_Fault';
			
			resp.method = method;
								 
			try {
				
				resp.resultFunction = this[resultFunction];
				
			} catch (e:Error) {
				logger.error('Result handler "' + resultFunction + '" is missing. Default invoked');
				resp.resultFunction = generic_Result;
			}
			 
			try {
				
				resp.faultFunction = this[faultFunction];
				
			} catch (e:Error) {
				//logger.info('Fault handler "' + faultFunction + '" is missing. Default invoked');
				resp.faultFunction = generic_Fault;
			}
			 
			return resp;		
		}
		
	}
}

